Note: Open Rproj first, then script. To easily use relative paths, click the down button next to knit and then click “Knit Directory –> Project Directory”. This should make loading and saving files much easier.

1. Load packages and input data

Load packages

library(edgeR, quietly = TRUE) #edgeR-v3.30.3
library(vegan, quietly = TRUE)
library(Dune, quietly = TRUE)
library(ggplot2, quietly = TRUE) #ggplot2-v3.3.5
library(tidyverse, quietly = TRUE) #tidyverse-v1.3.1
library(Rmisc, quietly = TRUE)
library(mixOmics, quietly = TRUE)
#library(ggridges)
#library(hrbrthemes)
#library(viridis)

Load the input file containing the treatment information

#treatment information
treatmentinfo <- read.csv("Sample_Info/samples_Pacuta.annotations.txt", header = TRUE, sep = "\t", fileEncoding="UTF-8-BOM") #read in file
top3groups <- c("Group2", "Group3", "Group6")
treatmentinfo <- filter(treatmentinfo, group%in%top3groups)
table(treatmentinfo$group)

Group2 Group3 Group6 
    34     24     27 

Load the input file containing the gene count matrix

#gene count matrix
gcount <- as.data.frame(read_delim("Genome_Info/Pocillopora_acuta_KBHIv2.gentrome.fa.gz.salmon.numreads.matrix", delim = "\t", col_names = TRUE, show_col_types = FALSE), fileEncoding="UTF-8-BOM") #read in file
rownames(gcount) <- gcount$Name #makes "Name" the rowname
gcount <- gcount[,-c(1)] #drops the "Name" column
gcount <- round(gcount) #round 
dim(gcount); head(gcount)[,1:3] #view dataset attributes
[1] 33259   119
gcount <- gcount[,treatmentinfo$sample]

Determine library size

libSize.df <- data.frame(libSize=colSums(gcount))

Make DGE object

DGEdat <- DGEList(counts=as.matrix(gcount), samples=treatmentinfo,
                  group=treatmentinfo$temp)
dim(DGEdat$counts)
[1] 33259    85

2. Pre-filtering

lib.sizes.cpm <- colSums(gcount)/1000000
lib.sizes.cpm <- tibble(sample=colnames(gcount), lib.size=lib.sizes.cpm)

keep <- rowSums(cpm(gcount) > 3.33) >= 2
table(keep)
keep
FALSE  TRUE 
12211 21048 
DGEdat <- DGEdat[keep, , keep.lib.sizes=FALSE]

3. Data normalization

DGEdat <- calcNormFactors(DGEdat)
DGEdat$samples

4. Plot global gene expression

Log transform the counts matrix for the next plots

DGEdat.cpm <- DGEdat #make a copy the edgeR dataset
DGEdat.cpm$counts <- cpm(DGEdat.cpm$counts, log=TRUE, prior.count=5) #log transform the copy for the next plots

Run a principle coordinates analysis, all samples

d <- data.frame(DGEdat.cpm$samples, name = colnames(DGEdat.cpm$counts), TP_temp=paste(DGEdat.cpm$samples$timename, DGEdat.cpm$samples$temp, sep="_")) #make a dataframe containing all plotting info
#d <- filter(d, temp=="Hot")
d$timename <- factor(d$timename, levels = c("0_hour", "6_hour", "12_hour", "30_hour", "1_week", "2_week", "4_week", "6_week", "8_week", "12_week"))
ncol(DGEdat.cpm$counts[,d$sample])
[1] 85
# Partial Least Squares Analysis
mixOmic_plsda <- plsda(t(DGEdat.cpm$counts[,d$sample]), d$timename, ncomp = 85)
plotVar(mixOmic_plsda, plot = F)
plsda_plot <- biplot(mixOmic_plsda, var.axes = TRUE, cutoff = .8, ind.names = F); plsda_plot

plotIndiv(mixOmic_plsda, ind.names = F, ellipse = TRUE, legend = TRUE)

Run a principle coordinates analysis, Hot samples

d <- data.frame(DGEdat.cpm$samples, name = colnames(DGEdat.cpm$counts), TP_temp=paste(DGEdat.cpm$samples$timename, DGEdat.cpm$samples$temp, sep="_")) #make a dataframe containing all plotting info
d$timename <- factor(d$timename, levels = c("0_hour", "6_hour", "12_hour", "30_hour", "1_week", "2_week", "4_week", "6_week", "8_week", "12_week"))
d <- filter(d, temp=="Hot")
ncol(DGEdat.cpm$counts[,d$sample])
[1] 44
# Partial Least Squares Analysis
mixOmic_plsda <- plsda(t(DGEdat.cpm$counts[,d$sample]), d$TP_temp, ncomp = 44)
plotVar(mixOmic_plsda, plot = F)
plsda_plot <- biplot(mixOmic_plsda, var.axes = TRUE, cutoff = .8, ind.names = F); plsda_plot

plotIndiv(mixOmic_plsda, ind.names = F, ellipse = TRUE, legend = TRUE)

Run a principle coordinates analysis, Amb samples

d <- data.frame(DGEdat.cpm$samples, name = colnames(DGEdat.cpm$counts), TP_temp=paste(DGEdat.cpm$samples$timename, DGEdat.cpm$samples$temp, sep="_")) #make a dataframe containing all plotting info
d$timename <- factor(d$timename, levels = c("0_hour", "6_hour", "12_hour", "30_hour", "1_week", "2_week", "4_week", "6_week", "8_week", "12_week"))
d <- filter(d, temp=="Amb")
ncol(DGEdat.cpm$counts[,d$sample])
[1] 41
# Partial Least Squares Analysis
mixOmic_plsda <- plsda(t(DGEdat.cpm$counts[,d$sample]), d$TP_temp, ncomp = 41)
plotVar(mixOmic_plsda, plot = F)
plsda_plot <- biplot(mixOmic_plsda, var.axes = TRUE, cutoff = .8, ind.names = F); plsda_plot

plotIndiv(mixOmic_plsda, ind.names = F, ellipse = TRUE, legend = TRUE)

Emma script

# set working directory and load necessary packages

library(reshape2)
#library(ggbiplot)
library(broom)  # devtools::install_github("tidymodels/broom")
library(cowplot)
library(ggpubr)
#library(ggfortify)
library(ggrepel)
library(gridExtra)
#library(ggforce)
# set seed
set.seed(54321)

Load datasets

d <- data.frame(DGEdat.cpm$samples, name = colnames(DGEdat.cpm$counts), TP_temp=paste(DGEdat.cpm$samples$timename, DGEdat.cpm$samples$temp, sep="_")) #make a dataframe 
d$timename <- factor(d$timename, levels = c("0_hour", "6_hour", "12_hour", "30_hour", "1_week", "2_week", "4_week", "6_week", "8_week", "12_week"))
#PCA
Mcap.pca.out <- prcomp(t(DGEdat.cpm$counts[,d$sample])) #, center=FALSE, scale=FALSE) #run PCA
M.summary <- summary(Mcap.pca.out); M.summary #view results
Importance of components:
                           PC1     PC2     PC3      PC4      PC5      PC6      PC7      PC8      PC9     PC10     PC11     PC12     PC13     PC14    PC15
Standard deviation     47.8457 39.3804 31.8471 23.44963 19.12449 16.68497 15.27388 14.09774 12.78940 11.69200 11.33499 10.95941 10.53431 10.13147 9.45036
Proportion of Variance  0.2376  0.1609  0.1053  0.05707  0.03796  0.02889  0.02421  0.02063  0.01698  0.01419  0.01333  0.01247  0.01152  0.01065 0.00927
Cumulative Proportion   0.2376  0.3985  0.5038  0.56085  0.59881  0.62770  0.65191  0.67253  0.68951  0.70370  0.71703  0.72950  0.74101  0.75166 0.76093
                          PC16    PC17    PC18    PC19    PC20    PC21    PC22   PC23    PC24    PC25    PC26    PC27    PC28    PC29    PC30    PC31    PC32
Standard deviation     9.07542 8.86547 8.54723 8.36652 8.11764 8.07213 7.72604 7.4751 7.33188 6.98285 6.81872 6.75749 6.59476 6.50150 6.39636 6.34873 6.27945
Proportion of Variance 0.00855 0.00816 0.00758 0.00726 0.00684 0.00676 0.00619 0.0058 0.00558 0.00506 0.00483 0.00474 0.00451 0.00439 0.00425 0.00418 0.00409
Cumulative Proportion  0.76948 0.77764 0.78522 0.79248 0.79932 0.80609 0.81228 0.8181 0.82366 0.82872 0.83354 0.83828 0.84280 0.84718 0.85143 0.85561 0.85970
                          PC33    PC34    PC35    PC36    PC37    PC38    PC39    PC40    PC41    PC42   PC43    PC44    PC45    PC46    PC47    PC48    PC49
Standard deviation     6.15489 6.07861 6.03575 5.97942 5.90674 5.84883 5.79111 5.76026 5.70003 5.66802 5.6388 5.61025 5.55841 5.49090 5.45282 5.42537 5.36089
Proportion of Variance 0.00393 0.00383 0.00378 0.00371 0.00362 0.00355 0.00348 0.00344 0.00337 0.00333 0.0033 0.00327 0.00321 0.00313 0.00309 0.00305 0.00298
Cumulative Proportion  0.86364 0.86747 0.87125 0.87496 0.87858 0.88213 0.88561 0.88906 0.89243 0.89576 0.8991 0.90233 0.90554 0.90866 0.91175 0.91481 0.91779
                          PC50    PC51    PC52    PC53   PC54    PC55    PC56    PC57    PC58    PC59    PC60    PC61    PC62    PC63    PC64   PC65    PC66
Standard deviation     5.33055 5.26422 5.23060 5.20470 5.1901 5.13711 5.12038 5.06910 5.04595 5.01429 4.99416 4.95214 4.93965 4.89052 4.84779 4.8065 4.78845
Proportion of Variance 0.00295 0.00288 0.00284 0.00281 0.0028 0.00274 0.00272 0.00267 0.00264 0.00261 0.00259 0.00255 0.00253 0.00248 0.00244 0.0024 0.00238
Cumulative Proportion  0.92074 0.92361 0.92645 0.92926 0.9321 0.93480 0.93752 0.94019 0.94283 0.94544 0.94803 0.95057 0.95310 0.95559 0.95802 0.9604 0.96280
                          PC67    PC68    PC69    PC70    PC71    PC72    PC73    PC74    PC75    PC76    PC77    PC78    PC79   PC80    PC81    PC82   PC83
Standard deviation     4.76581 4.74457 4.71724 4.67894 4.63921 4.58973 4.55821 4.53962 4.49122 4.47088 4.40430 4.37397 4.34636 4.2770 4.24909 4.21365 4.1665
Proportion of Variance 0.00236 0.00234 0.00231 0.00227 0.00223 0.00219 0.00216 0.00214 0.00209 0.00207 0.00201 0.00199 0.00196 0.0019 0.00187 0.00184 0.0018
Cumulative Proportion  0.96516 0.96749 0.96980 0.97208 0.97431 0.97650 0.97865 0.98079 0.98288 0.98496 0.98697 0.98896 0.99092 0.9928 0.99469 0.99653 0.9983
                          PC84      PC85
Standard deviation     4.00645 5.257e-14
Proportion of Variance 0.00167 0.000e+00
Cumulative Proportion  1.00000 1.000e+00
biplot(Mcap.pca.out) #plot results

Mcapitata.all <- Mcap.pca.out %>%
  augment(d) %>% # add original dataset back in
  group_by(timename, temp) %>%
  mutate(PC5.mean = mean(.fittedPC5),
         PC6.mean = mean(.fittedPC6))

mcap.Hot.segments <- Mcapitata.all %>% subset(temp == "Hot") %>%
  select(timename, temp, PC5.mean, PC6.mean) %>%
  gather(variable, value, -(timename:temp)) %>%
  unite(group, timename, variable) %>% distinct() %>%
  spread(group, value)

mcap.amb.segments <- Mcapitata.all %>% subset(temp == "Amb") %>%
  select(timename, temp, PC5.mean, PC6.mean) %>%
  gather(variable, value, -(timename:temp)) %>%
  unite(group, timename, variable) %>% distinct() %>%
  spread(group, value)

LS0tCnRpdGxlOiAiUExTLURBIG9mICpQLiBhY3V0YSogZ2VuZSBleHByZXNzaW9uIgphdXRob3I6ICJFcmluIENoaWxsZSIKZGF0ZTogIjA1LzA5LzIwMjQiCm91dHB1dDoKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKICBodG1sX25vdGVib29rOiBkZWZhdWx0Ci0tLQoKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQpybShsaXN0ID0gbHMoKSkgI2NsZWFyIGVudmlyb25tZW50CmBgYAoKKk5vdGU6IE9wZW4gUnByb2ogZmlyc3QsIHRoZW4gc2NyaXB0LiBUbyBlYXNpbHkgdXNlIHJlbGF0aXZlIHBhdGhzLCBjbGljayB0aGUgZG93biBidXR0b24gbmV4dCB0byBrbml0IGFuZCB0aGVuIGNsaWNrICJLbml0IERpcmVjdG9yeSAtLT4gUHJvamVjdCBEaXJlY3RvcnkiLiBUaGlzIHNob3VsZCBtYWtlIGxvYWRpbmcgYW5kIHNhdmluZyBmaWxlcyBtdWNoIGVhc2llci4qCgojIyAxLiBMb2FkIHBhY2thZ2VzIGFuZCBpbnB1dCBkYXRhCgpMb2FkIHBhY2thZ2VzCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KGVkZ2VSLCBxdWlldGx5ID0gVFJVRSkgI2VkZ2VSLXYzLjMwLjMKbGlicmFyeSh2ZWdhbiwgcXVpZXRseSA9IFRSVUUpCmxpYnJhcnkoRHVuZSwgcXVpZXRseSA9IFRSVUUpCmxpYnJhcnkoZ2dwbG90MiwgcXVpZXRseSA9IFRSVUUpICNnZ3Bsb3QyLXYzLjMuNQpsaWJyYXJ5KHRpZHl2ZXJzZSwgcXVpZXRseSA9IFRSVUUpICN0aWR5dmVyc2UtdjEuMy4xCmxpYnJhcnkoUm1pc2MsIHF1aWV0bHkgPSBUUlVFKQpsaWJyYXJ5KG1peE9taWNzLCBxdWlldGx5ID0gVFJVRSkKI2xpYnJhcnkoZ2dyaWRnZXMpCiNsaWJyYXJ5KGhyYnJ0aGVtZXMpCiNsaWJyYXJ5KHZpcmlkaXMpCgpgYGAKCkxvYWQgdGhlIGlucHV0IGZpbGUgY29udGFpbmluZyB0aGUgdHJlYXRtZW50IGluZm9ybWF0aW9uCmBgYHtyfQojdHJlYXRtZW50IGluZm9ybWF0aW9uCnRyZWF0bWVudGluZm8gPC0gcmVhZC5jc3YoIlNhbXBsZV9JbmZvL3NhbXBsZXNfUGFjdXRhLmFubm90YXRpb25zLnR4dCIsIGhlYWRlciA9IFRSVUUsIHNlcCA9ICJcdCIsIGZpbGVFbmNvZGluZz0iVVRGLTgtQk9NIikgI3JlYWQgaW4gZmlsZQp0b3AzZ3JvdXBzIDwtIGMoIkdyb3VwMiIsICJHcm91cDMiLCAiR3JvdXA2IikKdHJlYXRtZW50aW5mbyA8LSBmaWx0ZXIodHJlYXRtZW50aW5mbywgZ3JvdXAlaW4ldG9wM2dyb3VwcykKdGFibGUodHJlYXRtZW50aW5mbyRncm91cCkKYGBgCgpMb2FkIHRoZSBpbnB1dCBmaWxlIGNvbnRhaW5pbmcgdGhlIGdlbmUgY291bnQgbWF0cml4CmBgYHtyfQojZ2VuZSBjb3VudCBtYXRyaXgKZ2NvdW50IDwtIGFzLmRhdGEuZnJhbWUocmVhZF9kZWxpbSgiR2Vub21lX0luZm8vUG9jaWxsb3BvcmFfYWN1dGFfS0JISXYyLmdlbnRyb21lLmZhLmd6LnNhbG1vbi5udW1yZWFkcy5tYXRyaXgiLCBkZWxpbSA9ICJcdCIsIGNvbF9uYW1lcyA9IFRSVUUsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpLCBmaWxlRW5jb2Rpbmc9IlVURi04LUJPTSIpICNyZWFkIGluIGZpbGUKcm93bmFtZXMoZ2NvdW50KSA8LSBnY291bnQkTmFtZSAjbWFrZXMgIk5hbWUiIHRoZSByb3duYW1lCmdjb3VudCA8LSBnY291bnRbLC1jKDEpXSAjZHJvcHMgdGhlICJOYW1lIiBjb2x1bW4KZ2NvdW50IDwtIHJvdW5kKGdjb3VudCkgI3JvdW5kIApkaW0oZ2NvdW50KTsgaGVhZChnY291bnQpWywxOjNdICN2aWV3IGRhdGFzZXQgYXR0cmlidXRlcwpnY291bnQgPC0gZ2NvdW50Wyx0cmVhdG1lbnRpbmZvJHNhbXBsZV0KYGBgCgpEZXRlcm1pbmUgbGlicmFyeSBzaXplCmBgYHtyfQpsaWJTaXplLmRmIDwtIGRhdGEuZnJhbWUobGliU2l6ZT1jb2xTdW1zKGdjb3VudCkpCmBgYAoKTWFrZSBER0Ugb2JqZWN0CmBgYHtyfQpER0VkYXQgPC0gREdFTGlzdChjb3VudHM9YXMubWF0cml4KGdjb3VudCksIHNhbXBsZXM9dHJlYXRtZW50aW5mbywKICAgICAgICAgICAgICAgICAgZ3JvdXA9dHJlYXRtZW50aW5mbyR0ZW1wKQpkaW0oREdFZGF0JGNvdW50cykKYGBgCgojIyAyLiBQcmUtZmlsdGVyaW5nCmBgYHtyfQpsaWIuc2l6ZXMuY3BtIDwtIGNvbFN1bXMoZ2NvdW50KS8xMDAwMDAwCmxpYi5zaXplcy5jcG0gPC0gdGliYmxlKHNhbXBsZT1jb2xuYW1lcyhnY291bnQpLCBsaWIuc2l6ZT1saWIuc2l6ZXMuY3BtKQoKa2VlcCA8LSByb3dTdW1zKGNwbShnY291bnQpID4gMy4zMykgPj0gMgp0YWJsZShrZWVwKQpER0VkYXQgPC0gREdFZGF0W2tlZXAsICwga2VlcC5saWIuc2l6ZXM9RkFMU0VdCmBgYAoKIyMgIDMuIERhdGEgbm9ybWFsaXphdGlvbiAgCmBgYHtyfQpER0VkYXQgPC0gY2FsY05vcm1GYWN0b3JzKERHRWRhdCkKREdFZGF0JHNhbXBsZXMKYGBgCgojIyAgNC4gUGxvdCBnbG9iYWwgZ2VuZSBleHByZXNzaW9uICAKCkxvZyB0cmFuc2Zvcm0gdGhlIGNvdW50cyBtYXRyaXggZm9yIHRoZSBuZXh0IHBsb3RzCmBgYHtyfQpER0VkYXQuY3BtIDwtIERHRWRhdCAjbWFrZSBhIGNvcHkgdGhlIGVkZ2VSIGRhdGFzZXQKREdFZGF0LmNwbSRjb3VudHMgPC0gY3BtKERHRWRhdC5jcG0kY291bnRzLCBsb2c9VFJVRSwgcHJpb3IuY291bnQ9NSkgI2xvZyB0cmFuc2Zvcm0gdGhlIGNvcHkgZm9yIHRoZSBuZXh0IHBsb3RzCmBgYAoKUnVuIGEgcHJpbmNpcGxlIGNvb3JkaW5hdGVzIGFuYWx5c2lzLCBhbGwgc2FtcGxlcwpgYGB7cn0KZCA8LSBkYXRhLmZyYW1lKERHRWRhdC5jcG0kc2FtcGxlcywgbmFtZSA9IGNvbG5hbWVzKERHRWRhdC5jcG0kY291bnRzKSwgVFBfdGVtcD1wYXN0ZShER0VkYXQuY3BtJHNhbXBsZXMkdGltZW5hbWUsIERHRWRhdC5jcG0kc2FtcGxlcyR0ZW1wLCBzZXA9Il8iKSkgI21ha2UgYSBkYXRhZnJhbWUgY29udGFpbmluZyBhbGwgcGxvdHRpbmcgaW5mbwojZCA8LSBmaWx0ZXIoZCwgdGVtcD09IkhvdCIpCmQkdGltZW5hbWUgPC0gZmFjdG9yKGQkdGltZW5hbWUsIGxldmVscyA9IGMoIjBfaG91ciIsICI2X2hvdXIiLCAiMTJfaG91ciIsICIzMF9ob3VyIiwgIjFfd2VlayIsICIyX3dlZWsiLCAiNF93ZWVrIiwgIjZfd2VlayIsICI4X3dlZWsiLCAiMTJfd2VlayIpKQpuY29sKERHRWRhdC5jcG0kY291bnRzWyxkJHNhbXBsZV0pCiMgUGFydGlhbCBMZWFzdCBTcXVhcmVzIEFuYWx5c2lzCm1peE9taWNfcGxzZGEgPC0gcGxzZGEodChER0VkYXQuY3BtJGNvdW50c1ssZCRzYW1wbGVdKSwgZCR0aW1lbmFtZSwgbmNvbXAgPSA4NSkKcGxvdFZhcihtaXhPbWljX3Bsc2RhLCBwbG90ID0gRikKcGxzZGFfcGxvdCA8LSBiaXBsb3QobWl4T21pY19wbHNkYSwgdmFyLmF4ZXMgPSBUUlVFLCBjdXRvZmYgPSAuOCwgaW5kLm5hbWVzID0gRik7IHBsc2RhX3Bsb3QKcGxvdEluZGl2KG1peE9taWNfcGxzZGEsIGluZC5uYW1lcyA9IEYsIGVsbGlwc2UgPSBUUlVFLCBsZWdlbmQgPSBUUlVFKQpgYGAKClJ1biBhIHByaW5jaXBsZSBjb29yZGluYXRlcyBhbmFseXNpcywgSG90IHNhbXBsZXMKYGBge3J9CmQgPC0gZGF0YS5mcmFtZShER0VkYXQuY3BtJHNhbXBsZXMsIG5hbWUgPSBjb2xuYW1lcyhER0VkYXQuY3BtJGNvdW50cyksIFRQX3RlbXA9cGFzdGUoREdFZGF0LmNwbSRzYW1wbGVzJHRpbWVuYW1lLCBER0VkYXQuY3BtJHNhbXBsZXMkdGVtcCwgc2VwPSJfIikpICNtYWtlIGEgZGF0YWZyYW1lIGNvbnRhaW5pbmcgYWxsIHBsb3R0aW5nIGluZm8KZCR0aW1lbmFtZSA8LSBmYWN0b3IoZCR0aW1lbmFtZSwgbGV2ZWxzID0gYygiMF9ob3VyIiwgIjZfaG91ciIsICIxMl9ob3VyIiwgIjMwX2hvdXIiLCAiMV93ZWVrIiwgIjJfd2VlayIsICI0X3dlZWsiLCAiNl93ZWVrIiwgIjhfd2VlayIsICIxMl93ZWVrIikpCmQgPC0gZmlsdGVyKGQsIHRlbXA9PSJIb3QiKQpuY29sKERHRWRhdC5jcG0kY291bnRzWyxkJHNhbXBsZV0pCiMgUGFydGlhbCBMZWFzdCBTcXVhcmVzIEFuYWx5c2lzCm1peE9taWNfcGxzZGEgPC0gcGxzZGEodChER0VkYXQuY3BtJGNvdW50c1ssZCRzYW1wbGVdKSwgZCRUUF90ZW1wLCBuY29tcCA9IDQ0KQpwbG90VmFyKG1peE9taWNfcGxzZGEsIHBsb3QgPSBGKQpwbHNkYV9wbG90IDwtIGJpcGxvdChtaXhPbWljX3Bsc2RhLCB2YXIuYXhlcyA9IFRSVUUsIGN1dG9mZiA9IC44LCBpbmQubmFtZXMgPSBGKTsgcGxzZGFfcGxvdApwbG90SW5kaXYobWl4T21pY19wbHNkYSwgaW5kLm5hbWVzID0gRiwgZWxsaXBzZSA9IFRSVUUsIGxlZ2VuZCA9IFRSVUUpCmBgYAoKUnVuIGEgcHJpbmNpcGxlIGNvb3JkaW5hdGVzIGFuYWx5c2lzLCBBbWIgc2FtcGxlcwpgYGB7cn0KZCA8LSBkYXRhLmZyYW1lKERHRWRhdC5jcG0kc2FtcGxlcywgbmFtZSA9IGNvbG5hbWVzKERHRWRhdC5jcG0kY291bnRzKSwgVFBfdGVtcD1wYXN0ZShER0VkYXQuY3BtJHNhbXBsZXMkdGltZW5hbWUsIERHRWRhdC5jcG0kc2FtcGxlcyR0ZW1wLCBzZXA9Il8iKSkgI21ha2UgYSBkYXRhZnJhbWUgY29udGFpbmluZyBhbGwgcGxvdHRpbmcgaW5mbwpkJHRpbWVuYW1lIDwtIGZhY3RvcihkJHRpbWVuYW1lLCBsZXZlbHMgPSBjKCIwX2hvdXIiLCAiNl9ob3VyIiwgIjEyX2hvdXIiLCAiMzBfaG91ciIsICIxX3dlZWsiLCAiMl93ZWVrIiwgIjRfd2VlayIsICI2X3dlZWsiLCAiOF93ZWVrIiwgIjEyX3dlZWsiKSkKZCA8LSBmaWx0ZXIoZCwgdGVtcD09IkFtYiIpCm5jb2woREdFZGF0LmNwbSRjb3VudHNbLGQkc2FtcGxlXSkKIyBQYXJ0aWFsIExlYXN0IFNxdWFyZXMgQW5hbHlzaXMKbWl4T21pY19wbHNkYSA8LSBwbHNkYSh0KERHRWRhdC5jcG0kY291bnRzWyxkJHNhbXBsZV0pLCBkJFRQX3RlbXAsIG5jb21wID0gNDEpCnBsb3RWYXIobWl4T21pY19wbHNkYSwgcGxvdCA9IEYpCnBsc2RhX3Bsb3QgPC0gYmlwbG90KG1peE9taWNfcGxzZGEsIHZhci5heGVzID0gVFJVRSwgY3V0b2ZmID0gLjgsIGluZC5uYW1lcyA9IEYpOyBwbHNkYV9wbG90CnBsb3RJbmRpdihtaXhPbWljX3Bsc2RhLCBpbmQubmFtZXMgPSBGLCBlbGxpcHNlID0gVFJVRSwgbGVnZW5kID0gVFJVRSkKYGBgCgojIEVtbWEgc2NyaXB0CmBgYHtyfQojIHNldCB3b3JraW5nIGRpcmVjdG9yeSBhbmQgbG9hZCBuZWNlc3NhcnkgcGFja2FnZXMKCmxpYnJhcnkocmVzaGFwZTIpCiNsaWJyYXJ5KGdnYmlwbG90KQpsaWJyYXJ5KGJyb29tKSAgIyBkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoInRpZHltb2RlbHMvYnJvb20iKQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkoZ2dwdWJyKQojbGlicmFyeShnZ2ZvcnRpZnkpCmxpYnJhcnkoZ2dyZXBlbCkKbGlicmFyeShncmlkRXh0cmEpCiNsaWJyYXJ5KGdnZm9yY2UpCiMgc2V0IHNlZWQKc2V0LnNlZWQoNTQzMjEpCmBgYAoKTG9hZCBkYXRhc2V0cwpgYGB7cn0KZCA8LSBkYXRhLmZyYW1lKERHRWRhdC5jcG0kc2FtcGxlcywgbmFtZSA9IGNvbG5hbWVzKERHRWRhdC5jcG0kY291bnRzKSwgVFBfdGVtcD1wYXN0ZShER0VkYXQuY3BtJHNhbXBsZXMkdGltZW5hbWUsIERHRWRhdC5jcG0kc2FtcGxlcyR0ZW1wLCBzZXA9Il8iKSkgI21ha2UgYSBkYXRhZnJhbWUgCmQkdGltZW5hbWUgPC0gZmFjdG9yKGQkdGltZW5hbWUsIGxldmVscyA9IGMoIjBfaG91ciIsICI2X2hvdXIiLCAiMTJfaG91ciIsICIzMF9ob3VyIiwgIjFfd2VlayIsICIyX3dlZWsiLCAiNF93ZWVrIiwgIjZfd2VlayIsICI4X3dlZWsiLCAiMTJfd2VlayIpKQpgYGAKCmBgYHtyfQojUENBCk1jYXAucGNhLm91dCA8LSBwcmNvbXAodChER0VkYXQuY3BtJGNvdW50c1ssZCRzYW1wbGVdKSkgIywgY2VudGVyPUZBTFNFLCBzY2FsZT1GQUxTRSkgI3J1biBQQ0EKTS5zdW1tYXJ5IDwtIHN1bW1hcnkoTWNhcC5wY2Eub3V0KTsgTS5zdW1tYXJ5ICN2aWV3IHJlc3VsdHMKYmlwbG90KE1jYXAucGNhLm91dCkgI3Bsb3QgcmVzdWx0cwpgYGAKCmBgYHtyfQpNY2FwLnBjYS5vdXQgJT4lCiAgYXVnbWVudChkKSAlPiUgIyBhZGQgb3JpZ2luYWwgZGF0YXNldCBiYWNrIGluCiAgZ2dwbG90KGFlcyguZml0dGVkUEMxLCAuZml0dGVkUEM3LCBjb2xvciA9IGdyb3VwLjEpKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDMsIGNvbG9yPSdibGFjaycsIGFlcyhzaGFwZT10ZW1wLCBmaWxsPWdyb3VwLjEpKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKGd1aWRlPSJsZWdlbmQiLCB2YWx1ZXM9YygnQW1iJz0yMSwgJ0hvdCc9MjQpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwoZ3VpZGU9ImxlZ2VuZCIsIHZhbHVlcz1jKCdHcm91cDInPSIjRkZCRDVDIiwgJ0dyb3VwMyc9IiNCODczRkYiIywgJ0dyb3VwNic9IiM0RUI5MDAiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpICsKICAjeGxhYihwYXN0ZTAoIlBDMTogIiwgcm91bmQocGVyY2VudFZhclsxXSAqIDEwMCksICIlIHZhcmlhbmNlIikpICsKICAjeWxhYihwYXN0ZTAoIlBDNzogIiwgcm91bmQocGVyY2VudFZhcls3XSAqIDEwMCksICIlIHZhcmlhbmNlIikpICsKICBjb29yZF9maXhlZCgpICsKICB0aGVtZV9idygpICsgI1NldCBiYWNrZ3JvdW5kIGNvbG9yCiAgc3RhdF9lbGxpcHNlKCkgKwogIHRoZW1lKHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwgIyBTZXQgYm9yZGVyCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgI1NldCBtYWpvciBncmlkbGluZXMKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLCAjU2V0IG1pbm9yIGdyaWRsaW5lcwogICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gMC42KSwgI1NldCBheGVzIGNvbG9yCiAgICAgICAgcGxvdC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKSwgI1NldCB0aGUgcGxvdCBiYWNrZ3JvdW5kCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKSArICNBeGlzIHRpdGxlIHNpemV0CiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChzaGFwZT0yMSkpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMS41LCBhbHBoYT0wLjUpICsKICB0aGVtZV9oYWxmX29wZW4oMTIpICsgYmFja2dyb3VuZF9ncmlkKCkrCiAgc3RhdF9lbGxpcHNlKCkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgI2dndGl0bGUoIk1vbnRpcG9yYSBjYXBpdGF0YSIpICsgCiAgI2ZhY2V0X2dyaWQoY29scz12YXJzKHRpbWVuYW1lKSkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICdib2xkLml0YWxpYycsIHNpemUgPSAxNCwgaGp1c3QgPSAwKSkgKwogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTEyLCBmYWNlPSJib2xkIiksIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICNzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiZGVlcHNreWJsdWUiLCAiZmlyZWJyaWNrMSIpLCBhZXN0aGV0aWNzID0gYygiY29sb3VyIikpICsKICB4bGFiKCJQQzEgMjQlIikgKyB5bGFiKCJQQzcgMiUiKQoKTWNhcC5wY2Eub3V0ICU+JQogIGF1Z21lbnQoZCkgJT4lICMgYWRkIG9yaWdpbmFsIGRhdGFzZXQgYmFjayBpbgogIGdncGxvdChhZXMoLmZpdHRlZFBDNSwgLmZpdHRlZFBDNiwgY29sb3IgPSB0ZW1wKSkgKyAKICBnZW9tX3BvaW50KHNpemUgPSAxLjUsIGFscGhhPTAuNSkgKwogIHRoZW1lX2hhbGZfb3BlbigxMikgKyBiYWNrZ3JvdW5kX2dyaWQoKSsKICBzdGF0X2VsbGlwc2UoKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICAjZ2d0aXRsZSgiTW9udGlwb3JhIGNhcGl0YXRhIikgKyAKICBmYWNldF9ncmlkKGNvbHM9dmFycyh0aW1lbmFtZSkpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAnYm9sZC5pdGFsaWMnLCBzaXplID0gMTQsIGhqdXN0ID0gMCkpICsKICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xMiwgZmFjZT0iYm9sZCIpLCBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsKICAjc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoImRlZXBza3libHVlIiwgImZpcmVicmljazEiKSwgYWVzdGhldGljcyA9IGMoImNvbG91ciIpKSArCiAgeGxhYigiUEM1IDIzLjc2JSIpICsgeWxhYigiUEM2IDE2LjA5JSIpCmBgYAoKYGBge3J9Ck1jYXBpdGF0YS5hbGwgPC0gTWNhcC5wY2Eub3V0ICU+JQogIGF1Z21lbnQoZCkgJT4lICMgYWRkIG9yaWdpbmFsIGRhdGFzZXQgYmFjayBpbgogIGdyb3VwX2J5KHRpbWVuYW1lLCB0ZW1wKSAlPiUKICBtdXRhdGUoUEM1Lm1lYW4gPSBtZWFuKC5maXR0ZWRQQzUpLAogICAgICAgICBQQzYubWVhbiA9IG1lYW4oLmZpdHRlZFBDNikpCgptY2FwLkhvdC5zZWdtZW50cyA8LSBNY2FwaXRhdGEuYWxsICU+JSBzdWJzZXQodGVtcCA9PSAiSG90IikgJT4lCiAgc2VsZWN0KHRpbWVuYW1lLCB0ZW1wLCBQQzUubWVhbiwgUEM2Lm1lYW4pICU+JQogIGdhdGhlcih2YXJpYWJsZSwgdmFsdWUsIC0odGltZW5hbWU6dGVtcCkpICU+JQogIHVuaXRlKGdyb3VwLCB0aW1lbmFtZSwgdmFyaWFibGUpICU+JSBkaXN0aW5jdCgpICU+JQogIHNwcmVhZChncm91cCwgdmFsdWUpCgptY2FwLmFtYi5zZWdtZW50cyA8LSBNY2FwaXRhdGEuYWxsICU+JSBzdWJzZXQodGVtcCA9PSAiQW1iIikgJT4lCiAgc2VsZWN0KHRpbWVuYW1lLCB0ZW1wLCBQQzUubWVhbiwgUEM2Lm1lYW4pICU+JQogIGdhdGhlcih2YXJpYWJsZSwgdmFsdWUsIC0odGltZW5hbWU6dGVtcCkpICU+JQogIHVuaXRlKGdyb3VwLCB0aW1lbmFtZSwgdmFyaWFibGUpICU+JSBkaXN0aW5jdCgpICU+JQogIHNwcmVhZChncm91cCwgdmFsdWUpCmBgYAoKYGBge3J9Ck1jYXBpdGF0YS5hbGwuZmlnIDwtIGdncGxvdChNY2FwaXRhdGEuYWxsLCBhZXMoLmZpdHRlZFBDNSwgLmZpdHRlZFBDNiwgY29sb3IgPSBncm91cC4xKSkgKyAKICBnZW9tX3NlZ21lbnQoYWVzKHggPSBgMF9ob3VyX1BDNS5tZWFuYCwgeSA9IGAwX2hvdXJfUEM2Lm1lYW5gLCB4ZW5kID0gYDZfaG91cl9QQzUubWVhbmAsIHllbmQgPSBgNl9ob3VyX1BDNi5tZWFuYCwgY29sb3VyID0gdGVtcCksIGRhdGEgPSBtY2FwLkhvdC5zZWdtZW50cywgc2l6ZT0xLCBzaG93LmxlZ2VuZD1GQUxTRSkgKyAjIDBfaG91ciB0byA2X2hvdXIgSG90CiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gYDZfaG91cl9QQzUubWVhbmAsIHkgPSBgNl9ob3VyX1BDNi5tZWFuYCwgeGVuZCA9IGAxMl9ob3VyX1BDNS5tZWFuYCwgeWVuZCA9IGAxMl9ob3VyX1BDNi5tZWFuYCwgY29sb3VyID0gdGVtcCksIGRhdGEgPSBtY2FwLkhvdC5zZWdtZW50cywgc2l6ZT0xLCBzaG93LmxlZ2VuZD1GQUxTRSkgKyAjIDZfaG91ciB0byAxMl9ob3VyIEhvdAogICAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gYDEyX2hvdXJfUEM1Lm1lYW5gLCB5ID0gYDEyX2hvdXJfUEM2Lm1lYW5gLCB4ZW5kID0gYDMwX2hvdXJfUEM1Lm1lYW5gLCB5ZW5kID0gYDMwX2hvdXJfUEM2Lm1lYW5gLCBjb2xvdXIgPSB0ZW1wKSwgZGF0YSA9IG1jYXAuSG90LnNlZ21lbnRzLCBzaXplPTEsIHNob3cubGVnZW5kPUZBTFNFKSArICMgMTJfaG91ciB0byAzMF9ob3VyIEhvdAogICAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gYDMwX2hvdXJfUEM1Lm1lYW5gLCB5ID0gYDMwX2hvdXJfUEM2Lm1lYW5gLCB4ZW5kID0gYDFfd2Vla19QQzUubWVhbmAsIHllbmQgPSBgMV93ZWVrX1BDNi5tZWFuYCwgY29sb3VyID0gdGVtcCksIGRhdGEgPSBtY2FwLkhvdC5zZWdtZW50cywgc2l6ZT0xLCBzaG93LmxlZ2VuZD1GQUxTRSkgKyAjIDMwX2hvdXIgdG8gMV93ZWVrIEhvdAogICAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSBgMV93ZWVrX1BDNS5tZWFuYCwgeSA9IGAxX3dlZWtfUEM2Lm1lYW5gLCB4ZW5kID0gYDJfd2Vla19QQzUubWVhbmAsIHllbmQgPSBgMl93ZWVrX1BDNi5tZWFuYCwgY29sb3VyID0gdGVtcCksIGRhdGEgPSBtY2FwLkhvdC5zZWdtZW50cywgc2l6ZT0xLCBzaG93LmxlZ2VuZD1GQUxTRSkgKyAjIDFfd2VlayB0byAyX3dlZWsgSG90CiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gYDJfd2Vla19QQzUubWVhbmAsIHkgPSBgMl93ZWVrX1BDNi5tZWFuYCwgeGVuZCA9IGA0X3dlZWtfUEM1Lm1lYW5gLCB5ZW5kID0gYDRfd2Vla19QQzYubWVhbmAsIGNvbG91ciA9IHRlbXApLCBkYXRhID0gbWNhcC5Ib3Quc2VnbWVudHMsIHNpemU9MSwgc2hvdy5sZWdlbmQ9RkFMU0UpICsgIyAyX3dlZWsgdG8gNF93ZWVrIEhvdAogICAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gYDRfd2Vla19QQzUubWVhbmAsIHkgPSBgNF93ZWVrX1BDNi5tZWFuYCwgeGVuZCA9IGA2X3dlZWtfUEM1Lm1lYW5gLCB5ZW5kID0gYDZfd2Vla19QQzYubWVhbmAsIGNvbG91ciA9IHRlbXApLCBkYXRhID0gbWNhcC5Ib3Quc2VnbWVudHMsIHNpemU9MSwgc2hvdy5sZWdlbmQ9RkFMU0UpICsgIyA0X3dlZWsgdG8gOF93ZWVrIEhvdAogIGdlb21fc2VnbWVudChhZXMoeCA9IGA2X3dlZWtfUEM1Lm1lYW5gLCB5ID0gYDZfd2Vla19QQzYubWVhbmAsIHhlbmQgPSBgOF93ZWVrX1BDNS5tZWFuYCwgeWVuZCA9IGA4X3dlZWtfUEM2Lm1lYW5gLCBjb2xvdXIgPSB0ZW1wKSwgZGF0YSA9IG1jYXAuSG90LnNlZ21lbnRzLCBzaXplPTEsIHNob3cubGVnZW5kPUZBTFNFKSArICMgNF93ZWVrIHRvIDhfd2VlayBIb3QKICBnZW9tX3NlZ21lbnQoYWVzKHggPSBgOF93ZWVrX1BDNS5tZWFuYCwgeSA9IGA4X3dlZWtfUEM2Lm1lYW5gLCB4ZW5kID0gYDEyX3dlZWtfUEM1Lm1lYW5gLCB5ZW5kID0gYDEyX3dlZWtfUEM2Lm1lYW5gLCBjb2xvdXIgPSB0ZW1wKSwgZGF0YSA9IG1jYXAuSG90LnNlZ21lbnRzLCBzaXplPTEsIHNob3cubGVnZW5kPUZBTFNFLCBhcnJvdyA9IGFycm93KCkpICsgIyA4X3dlZWsgdG8gMTJfd2VlayBIb3QKICBnZW9tX3NlZ21lbnQoYWVzKHggPSBgMF9ob3VyX1BDNS5tZWFuYCwgeSA9IGAwX2hvdXJfUEM2Lm1lYW5gLCB4ZW5kID0gYDZfaG91cl9QQzUubWVhbmAsIHllbmQgPSBgNl9ob3VyX1BDNi5tZWFuYCwgY29sb3VyID0gdGVtcCksIGRhdGEgPSBtY2FwLmFtYi5zZWdtZW50cywgc2l6ZT0xLCBzaG93LmxlZ2VuZD1GQUxTRSkgKyAjIDBfaG91ciB0byA2X2hvdXIgYW1iCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gYDZfaG91cl9QQzUubWVhbmAsIHkgPSBgNl9ob3VyX1BDNi5tZWFuYCwgeGVuZCA9IGAxMl9ob3VyX1BDNS5tZWFuYCwgeWVuZCA9IGAxMl9ob3VyX1BDNi5tZWFuYCwgY29sb3VyID0gdGVtcCksIGRhdGEgPSBtY2FwLmFtYi5zZWdtZW50cywgc2l6ZT0xLCBzaG93LmxlZ2VuZD1GQUxTRSkgKyAjIDZfaG91ciB0byAxMl9ob3VyIGFtYgogICAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gYDEyX2hvdXJfUEM1Lm1lYW5gLCB5ID0gYDEyX2hvdXJfUEM2Lm1lYW5gLCB4ZW5kID0gYDMwX2hvdXJfUEM1Lm1lYW5gLCB5ZW5kID0gYDMwX2hvdXJfUEM2Lm1lYW5gLCBjb2xvdXIgPSB0ZW1wKSwgZGF0YSA9IG1jYXAuYW1iLnNlZ21lbnRzLCBzaXplPTEsIHNob3cubGVnZW5kPUZBTFNFKSArICMgMTJfaG91ciB0byAzMF9ob3VyIGFtYgogICAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gYDMwX2hvdXJfUEM1Lm1lYW5gLCB5ID0gYDMwX2hvdXJfUEM2Lm1lYW5gLCB4ZW5kID0gYDFfd2Vla19QQzUubWVhbmAsIHllbmQgPSBgMV93ZWVrX1BDNi5tZWFuYCwgY29sb3VyID0gdGVtcCksIGRhdGEgPSBtY2FwLmFtYi5zZWdtZW50cywgc2l6ZT0xLCBzaG93LmxlZ2VuZD1GQUxTRSkgKyAjIDMwX2hvdXIgdG8gMV93ZWVrIGFtYgogICAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSBgMV93ZWVrX1BDNS5tZWFuYCwgeSA9IGAxX3dlZWtfUEM2Lm1lYW5gLCB4ZW5kID0gYDJfd2Vla19QQzUubWVhbmAsIHllbmQgPSBgMl93ZWVrX1BDNi5tZWFuYCwgY29sb3VyID0gdGVtcCksIGRhdGEgPSBtY2FwLmFtYi5zZWdtZW50cywgc2l6ZT0xLCBzaG93LmxlZ2VuZD1GQUxTRSkgKyAjIDFfd2VlayB0byAyX3dlZWsgYW1iCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gYDJfd2Vla19QQzUubWVhbmAsIHkgPSBgMl93ZWVrX1BDNi5tZWFuYCwgeGVuZCA9IGA0X3dlZWtfUEM1Lm1lYW5gLCB5ZW5kID0gYDRfd2Vla19QQzYubWVhbmAsIGNvbG91ciA9IHRlbXApLCBkYXRhID0gbWNhcC5hbWIuc2VnbWVudHMsIHNpemU9MSwgc2hvdy5sZWdlbmQ9RkFMU0UpICsgIyAyX3dlZWsgdG8gNF93ZWVrIEFNQgogICAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gYDRfd2Vla19QQzUubWVhbmAsIHkgPSBgNF93ZWVrX1BDNi5tZWFuYCwgeGVuZCA9IGA2X3dlZWtfUEM1Lm1lYW5gLCB5ZW5kID0gYDZfd2Vla19QQzYubWVhbmAsIGNvbG91ciA9IHRlbXApLCBkYXRhID0gbWNhcC5hbWIuc2VnbWVudHMsIHNpemU9MSwgc2hvdy5sZWdlbmQ9RkFMU0UpICsgIyA0X3dlZWsgdG8gOF93ZWVrIGFtYgogIGdlb21fc2VnbWVudChhZXMoeCA9IGA2X3dlZWtfUEM1Lm1lYW5gLCB5ID0gYDZfd2Vla19QQzYubWVhbmAsIHhlbmQgPSBgOF93ZWVrX1BDNS5tZWFuYCwgeWVuZCA9IGA4X3dlZWtfUEM2Lm1lYW5gLCBjb2xvdXIgPSB0ZW1wKSwgZGF0YSA9IG1jYXAuYW1iLnNlZ21lbnRzLCBzaXplPTEsIHNob3cubGVnZW5kPUZBTFNFKSArICMgNF93ZWVrIHRvIDhfd2VlayBhbWIKICBnZW9tX3NlZ21lbnQoYWVzKHggPSBgOF93ZWVrX1BDNS5tZWFuYCwgeSA9IGA4X3dlZWtfUEM2Lm1lYW5gLCB4ZW5kID0gYDEyX3dlZWtfUEM1Lm1lYW5gLCB5ZW5kID0gYDEyX3dlZWtfUEM2Lm1lYW5gLCBjb2xvdXIgPSB0ZW1wKSwgZGF0YSA9IG1jYXAuYW1iLnNlZ21lbnRzLCBzaXplPTEsIHNob3cubGVnZW5kPUZBTFNFLCBhcnJvdyA9IGFycm93KCkpICsgIyA4X3dlZWsgdG8gMTJfd2VlayBBTUIKICBnZW9tX3BvaW50KHNpemUgPSAxLjUsIGFscGhhPTAuMykgKwogIGdlb21fcG9pbnQoYWVzKHg9UEM1Lm1lYW4sIHk9UEM2Lm1lYW4pLCBjb2xvcj0iZGFya2dyZXkiKSArCiAgZ2VvbV90ZXh0KHNpemUgPSAyLCBhZXMoUEM1Lm1lYW4sIFBDNi5tZWFuLCBsYWJlbD10aW1lbmFtZSksIHZqdXN0PS0xLjUsIGNvbG9yPSJibGFjayIpICsKICB0aGVtZV9oYWxmX29wZW4oMTIpICsgYmFja2dyb3VuZF9ncmlkKCkgKwogICNnZ3RpdGxlKCJNb250aXBvcmEgY2FwaXRhdGEiKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC44LCAwLjkpKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gJ2JvbGQuaXRhbGljJywgc2l6ZSA9IDE0LCBoanVzdCA9IDApKSArCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTIsIGZhY2U9ImJvbGQiKSkgKwogICNzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiZGVlcHNreWJsdWUiLCAiZmlyZWJyaWNrMSIpLCBhZXN0aGV0aWNzID0gYygiY29sb3VyIikpICsKICB4bGFiKCJQQzUgMjMuNzYlIikgKyB5bGFiKCJQQzYgMTYuMDklIik7IE1jYXBpdGF0YS5hbGwuZmlnCk1jYXBpdGF0YS5hbGwuZmlnIApnZ3NhdmUoIk91dHB1dC8xYy1QYWN1LWVkZ2VSLWFsbHNhbXBsZXMtUENBLXRpbWVuYW1lLWFycm93cy5wZGYiLCBNY2FwaXRhdGEuYWxsLmZpZywgd2lkdGggPSA2LCBoZWlnaHQgPSA1LCB1bml0cyA9IGMoImluIikpCmBgYA==